1 package org.apache.lucene.index;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.io.IOException;
21 import java.util.Collections;
22 import java.util.IdentityHashMap;
23 import java.util.List;
24 import java.util.Set;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class ParallelCompositeReader extends BaseCompositeReader<LeafReader> {
51 private final boolean closeSubReaders;
52 private final Set<IndexReader> completeReaderSet =
53 Collections.newSetFromMap(new IdentityHashMap<IndexReader,Boolean>());
54
55
56
57 public ParallelCompositeReader(CompositeReader... readers) throws IOException {
58 this(true, readers);
59 }
60
61
62
63 public ParallelCompositeReader(boolean closeSubReaders, CompositeReader... readers) throws IOException {
64 this(closeSubReaders, readers, readers);
65 }
66
67
68
69
70 public ParallelCompositeReader(boolean closeSubReaders, CompositeReader[] readers, CompositeReader[] storedFieldReaders) throws IOException {
71 super(prepareLeafReaders(readers, storedFieldReaders));
72 this.closeSubReaders = closeSubReaders;
73 Collections.addAll(completeReaderSet, readers);
74 Collections.addAll(completeReaderSet, storedFieldReaders);
75
76 if (!closeSubReaders) {
77 for (final IndexReader reader : completeReaderSet) {
78 reader.incRef();
79 }
80 }
81
82 completeReaderSet.addAll(getSequentialSubReaders());
83 }
84
85 private static LeafReader[] prepareLeafReaders(CompositeReader[] readers, CompositeReader[] storedFieldsReaders) throws IOException {
86 if (readers.length == 0) {
87 if (storedFieldsReaders.length > 0)
88 throw new IllegalArgumentException("There must be at least one main reader if storedFieldsReaders are used.");
89 return new LeafReader[0];
90 } else {
91 final List<? extends LeafReaderContext> firstLeaves = readers[0].leaves();
92
93
94 final int maxDoc = readers[0].maxDoc(), noLeaves = firstLeaves.size();
95 final int[] leafMaxDoc = new int[noLeaves];
96 for (int i = 0; i < noLeaves; i++) {
97 final LeafReader r = firstLeaves.get(i).reader();
98 leafMaxDoc[i] = r.maxDoc();
99 }
100 validate(readers, maxDoc, leafMaxDoc);
101 validate(storedFieldsReaders, maxDoc, leafMaxDoc);
102
103
104
105 final LeafReader[] wrappedLeaves = new LeafReader[noLeaves];
106 for (int i = 0; i < wrappedLeaves.length; i++) {
107 final LeafReader[] subs = new LeafReader[readers.length];
108 for (int j = 0; j < readers.length; j++) {
109 subs[j] = readers[j].leaves().get(i).reader();
110 }
111 final LeafReader[] storedSubs = new LeafReader[storedFieldsReaders.length];
112 for (int j = 0; j < storedFieldsReaders.length; j++) {
113 storedSubs[j] = storedFieldsReaders[j].leaves().get(i).reader();
114 }
115
116
117 wrappedLeaves[i] = new ParallelLeafReader(true, subs, storedSubs) {
118 @Override
119 protected void doClose() {}
120 };
121 }
122 return wrappedLeaves;
123 }
124 }
125
126 private static void validate(CompositeReader[] readers, int maxDoc, int[] leafMaxDoc) {
127 for (int i = 0; i < readers.length; i++) {
128 final CompositeReader reader = readers[i];
129 final List<? extends LeafReaderContext> subs = reader.leaves();
130 if (reader.maxDoc() != maxDoc) {
131 throw new IllegalArgumentException("All readers must have same maxDoc: "+maxDoc+"!="+reader.maxDoc());
132 }
133 final int noSubs = subs.size();
134 if (noSubs != leafMaxDoc.length) {
135 throw new IllegalArgumentException("All readers must have same number of leaf readers");
136 }
137 for (int subIDX = 0; subIDX < noSubs; subIDX++) {
138 final LeafReader r = subs.get(subIDX).reader();
139 if (r.maxDoc() != leafMaxDoc[subIDX]) {
140 throw new IllegalArgumentException("All leaf readers must have same corresponding subReader maxDoc");
141 }
142 }
143 }
144 }
145
146 @Override
147 protected synchronized void doClose() throws IOException {
148 IOException ioe = null;
149 for (final IndexReader reader : completeReaderSet) {
150 try {
151 if (closeSubReaders) {
152 reader.close();
153 } else {
154 reader.decRef();
155 }
156 } catch (IOException e) {
157 if (ioe == null) ioe = e;
158 }
159 }
160
161 if (ioe != null) throw ioe;
162 }
163 }